/**
 * Copy directory into destination dir (css and js)
 */
function copyDirectory(dir, context) {
   IO.makeDir(context.d + dir);
	var folderFiles = IO.ls([context.t + dir]);
	for (var i = 0 ; i < folderFiles.length; i++) {
		IO.copyFile(folderFiles[i], context.d + dir);
	}
}

function isset (val) { return (typeof(val) != 'undefined') && (val != null); }
function isaFile($) {return ($.is("FILE"));}
function isaClass($) {return ($.is("CONSTRUCTOR") || $.isNamespace);}
   
/**
 * Functions to sort by name or Alias
 */
function byName(a, b) {
	if (a.name != undefined && b.name != undefined) {
		a = a.name.toLowerCase();
		b = b.name.toLowerCase();
		if (a < b) return -1;
		if (a > b) return 1;
		return 0;
	}
}

function byAlias(a, b) {
	if (a.alias != undefined && b.alias != undefined) {
		a = a.alias.toLowerCase();
		b = b.alias.toLowerCase();
		if (a < b) return -1;
		if (a > b) return 1;
		return 0;
	}
}

// Global template for layout
var layoutTpl = null;

// Object containing the information for the layout
var layoutData = null;

/**
 * Render a file using the layout template
 */
function renderFile(filename, title, content) {
   layoutData.title = title;
   layoutData.layoutContent = content;
   var content = layoutTpl.process(layoutData);
   IO.saveFile(JSDOC.opt.d, filename, content);
}


/**
 * Entry point for jsdoc-toolkit-2.0.0
 */
function publish(symbolSet) {
   
   // Build the config object
	var config     = JSDOC.opt.config || {};
	config.indexFile = isset(config.indexFile)   ? config.indexFile   : null;
	config.link   = isset(config.link)   ? config.link   : '..';
	config.title   = isset(config.title)   ? config.title   : 'JsDoc';
	config.pages   = isset(config.pages)   ? config.pages   : [];
	config.version = isset(config.version)   ? config.version   : "0.0.1";
	config.copyright   = isset(config.copyright)   ? config.copyright   : 'copyright';
	
	/**
	 * Build the data object which will be passed to 
	 * the template files.
	 */
	layoutData = { 
	   config: config,
	   // Contains file informations
	   srcFiles: [], 
	   // List of all classes
	   srcClasses: [],
	   // List of all symbols
	   symbolList: symbolSet
	};
   
   // Generate the layoutData.files content:
 	for (var i = 0, l = JSDOC.opt.srcFiles.length; i < l; i++) {
 		var srcFile = JSDOC.opt.srcFiles[i];
		var t = srcFile.split('/');
		var name = t[t.length-1];
		layoutData.srcFiles[i] = {
		   path        : srcFile,
			name        : name,
			file        : name+'.html'
		};
 	}
 	
 	// Structure to build the treeview
	var treeview = [];
	
	// Structure to contain the "known subclasses"
	var subclasses = [];
 	
 	// Classes :
 	for(var symbolName in symbolSet["_index"] ) {
 	   if(symbolSet["_index"].hasOwnProperty(symbolName)) {
 	      var symbol = symbolSet["_index"][symbolName];
 	      if(isaClass(symbol) && symbolName != "_global_") {
 	         symbol.file = symbolName+".html";
 	         layoutData.srcClasses.push(symbol);
 	         
         	// Build the parentClass array for the treeview and the known subclasses
         	if(!symbol.isNamespace) {
 	            treeview[symbol.alias] = "Object";
         	   if(symbol.augments && symbol.augments.length > 0 ) {
            	   for(var k = 0 ; k < symbol.augments.length ; k++) {
            	      if(!subclasses[symbol.augments[k]]) { subclasses[symbol.augments[k]] = []; }
               	   subclasses[symbol.augments[k]].push(symbol.alias);
            	      treeview[symbol.alias] = symbol.augments[k];
            	   }
         	   }
      	   }
         	
 	      }
 	   }
 	}
 	
	// Sort classes and files by name
	layoutData.srcClasses.sort(byAlias);
	layoutData.srcFiles.sort(byName);




	// Templates :
   layoutTpl = new JSDOC.JsPlate(JSDOC.opt.t + 'templates/layout.tpl');
	
	// Process the "jsFiles" templates
   var jsTpl = new JSDOC.JsPlate(JSDOC.opt.t + 'templates/jsFile.tpl');
	for (var i = 0 ; i < layoutData.srcFiles.length; i++) {
	   var file = layoutData.srcFiles[i];
   	var content = jsTpl.process({
	      code: IO.readFile(file.path),
	      sourceFileName: file.name  
	   });
   	renderFile(file.file, file.name, content);
   }
   
   // Process the "class" templates
   var classTpl = new JSDOC.JsPlate(JSDOC.opt.t + 'templates/class.tpl');
	for (var i = 0 ; i < layoutData.srcClasses.length; i++) {
	   
	   var thisClass = layoutData.srcClasses[i];
		
		// Add inherited methods informations
		thisClass.inherited = {};
		for (var n = 0; n < thisClass.methods.length; n++) {   
			var method = thisClass.methods[n];
			var inheritFrom = method.memberOf;
		   if(inheritFrom != thisClass.alias) {
				if (!thisClass.inherited[inheritFrom]) thisClass.inherited[inheritFrom] = [];
				thisClass.inherited[inheritFrom].push(method);
			}
		}
		
		
		if(subclasses[thisClass.alias]) {
		   thisClass.subclasses = subclasses[thisClass.alias];
		}
		
      var content = classTpl.process([thisClass]);
   	renderFile(layoutData.srcClasses[i].alias+'.html', thisClass.alias, content);
   }

   
	// Process the pages template
   var pageTpl = new JSDOC.JsPlate(JSDOC.opt.t + 'templates/page.tpl');
	for(var i = 0 ; i < config.pages.length ; i++) {
	   var page = config.pages[i];
   	var content = pageTpl.process({pageContent: IO.readFile(page.src)});
   	renderFile(page.file, page.title, content);
	}
   
   // Build the treeview page
   var displayTree = function(cl) {
      var ret = (cl == "Object") ? "<ul>" : "<a href='"+cl+".html'>"+cl+"</a><ul>";
      for(c in treeview) {
         if( treeview.hasOwnProperty(c) ) {
            if(treeview[c] == cl) {
      	      ret+= "<li>"+displayTree(c)+"</li>";
   	      }
         }
      }
      return ret+"</ul>";
   };
	var content = pageTpl.process({pageContent: "<h1>Class Hierarchy</h1>"+displayTree('Object') });
	renderFile('treeview.html',  'Class Tree View', content);
	
	
	// Copy static files into destination folder
   copyDirectory('css', JSDOC.opt);
   copyDirectory('js', JSDOC.opt);
}


